#include <Core/DefaultCommandScheduler.h>

#include <boost/assert.hpp>

#define STD_EXCEPTION_SAFE_BEGIN try {
#define STD_EXCEPTION_SAFE_END(x) } catch (std::exception const & expt) { x; }

namespace Core {

/**
 *	Singleton instance for better using
 */
namespace Aux {

static boost::shared_ptr<DefaultCommandScheduler> defaultSchedulerRef;

} // namespace Aux

/**
 * Public DefaultCommandScheduler's api
 */
DefaultCommandScheduler::DefaultCommandScheduler(DefaultCommandSchedulerParams const & params) : 
	BoxCore::IBoxCommandIFace(), 
	m_scheduler(params.concurrency), 
	m_params(params) 
{ 
}

DefaultCommandScheduler::~DefaultCommandScheduler() throw () 
{ 
	interrupt(true);
}

void DefaultCommandScheduler::initialize() throw (std::exception) 
{ 
	// Self static initializetion
}
	
bool DefaultCommandScheduler::spawn(
	SyncedCommandIOStreamPtr stream,
	BoxCore::IBoxCommandIFace::SpawnCompeletionFunc spawnCompeletion) throw ()
{
	STD_EXCEPTION_SAFE_BEGIN
	
	ICommandPtr command = CommandCreateAdapters::unPack<ProtobufCommandTranslator>(stream);	
	if (command) { 
		command->setIOFace(stream);
		m_scheduler.schedule(
			boost::bind(&DefaultCommandScheduler::executeCommand, 
			this, command, spawnCompeletion, stream)); 
	}
	else { 
		//TODO Log this! 
	}

	STD_EXCEPTION_SAFE_END(return false)
			
	return true;
}

void DefaultCommandScheduler::interrupt(bool graceful) throw () 
{ 
	// TODO impl this
}

void DefaultCommandScheduler::run() throw (std::exception) 
{ 
	// self running  
}

/**
 * Helpers
 */
void initializeDefaultCommandScheduler(DefaultCommandSchedulerParams const & params) throw (std::exception) 
{
	Aux::defaultSchedulerRef.reset(new DefaultCommandScheduler(params));
}

DefaultCommandSchedulerPtr defaultScheduler() throw (std::exception)
{
	BOOST_ASSERT(Aux::defaultSchedulerRef != NULL);
	if (!Aux::defaultSchedulerRef)
		throw (std::runtime_error("The Default command scheduler not initialized, "
				"call Core::initializeDefaultCommandScheduler before use this function"));
	return Aux::defaultSchedulerRef;
}

} // Core

#undef STD_EXCEPTION_SAFE_BEGIN
#undef STD_EXCEPTION_SAFE_END


